<?php 
// php类的特点
// 继承 多态和oc的一样
//重载 − 简单说，就是函数或者方法有”同样的名称“，但是参数列表不相同的情形，这样的同名不同参数的函数或者方法之间，互相称之为重载函数或者方法。
//构造函数 − 主要用来在创建对象时初始化对象， 即为对象成员变量赋初始值，总与new运算符一起使用在创建对象的语句中
//析构函数 − 析构函数(destructor) 与构造函数相反，当对象结束其生命周期时（例如对象所在的函数已调用完毕），系统自动执行析构函数。析构函数往往用来做"清理善后" 的工作（例如在建立对象时用new开辟了一片内存空间，应在退出前在析构函数中用delete释放）。

$globalVar='我是全局变量'.'<br>';
 function globalVarFun()
{
  //static当一个函数完成时，它的所有变量通常都会被删除。然而，有时候您希望某个局部变量不要被删除
  static $staticVar=1;
  $staticVar++;
  echo $staticVar."静态局部变量"."<br>";
  global $globalVar;
  echo $globalVar;
}
globalVarFun();
 /**
 * 
 */
 class Car
 {
// 变量 $this 代表自身的对象。
// PHP_EOL 为换行符(貌似没用)
 	var $var1;
// 	类的变量使用 var 来声明, 变量也可以初始化值,不同于以前直接用“$”
 	var $var2='my name is car';
 	//构造函数 实例方法，类似oc的init
 	//php中实例方法只能有一个，如果没有，系统有默认的，通过new创建对象时可以不用小括号
 	function __construct($var)
 	{
    //global用语函数内访问全局变量，注意是函数内，在函数内用global定义
    global $globalVar;
    echo $globalVar;
 	//$this代表对象本身，用->访问对象的属性和方法，注意：访问属性直接跟属性名，不需要“$”符号
 		$this->var1=$var;
 	}
//析构函数，dealloc
   function __destruct(){

   print("销毁".$this->var1."<br>");


   }
    public function describeCar()
    {
    	$this->privateFunc();//只能在内部调用
    	echo "var1:".$this->var1."     "."var2:".$this->var2."<br>";
    }
   private function privateFunc()
   {
   	echo "我是私有方法"."<br>";
   }
   protected function protectFun(){

    echo "我是protect方法"."<br";
   }
 }
$car1=new Car('aaaa');
$car1->describeCar();
$car2=new Car('bbbb');
$car2->describeCar();
// $car2->protectFun();();//这会产生一个错误,这个方法只能在class的内部访问，可以被继承,不对外公开
// $car2->privateFunc();//这会产生一个错误,这个方法只能在class的内部访问，不能被继承,不对外公开

//继承
/**
* 继承用关键字extends
*/
class Truck extends Car
{
// public（公有）：公有的类成员可以在任何地方被访问。
// protected（受保护）：受保护的类成员则可以被其自身以及其子类和父类访问。
// private（私有）：私有的类成员则只能被其定义所在的类访问。
  var $name;
  //静态变量不是单纯的某个类的对象所持有的，他是这个类所有对象共有的，所以用本类（self）调用，并且不用var关键字
  static  $selfVar="我是通过self调用的"."<br>";

//常量,用类（self）或parent调用
  const constantVar="我是常量";
// 方法重写
// 如果从父类继承的方法不能满足子类的需求，可以对其进行改写，这个过程叫方法的覆盖（override），也称为方法的重写。
//此处重写了describeCar和构造函数,一个方法只能又一个构造函数或不写，用系统的
  public function describeCar(){
    //用self调用常量
    echo self::constantVar.__LINE__;
//     self:意思是本类
// parent意思是父类
    //通过类调用的不能用->访问，要用::
    parent::describeCar();
    echo self::$selfVar;
    echo "我是子类Truck"."   name:".$this->name."<br>";

  }
  public function textFun()
  {
    $this->protectFun();
    // $this->privateFunc();
  }
  public function __construct()
  {
  	
  }


}

$truck1=new Truck();
$truck1->name='truck';
$truck1->describeCar();
$truck1->textFun();

//接口 使用接口（interface），可以指定某个类必须实现哪些方法，但不需要定义这些方法的具体内容。
//接口中定义的所有方法都必须是"公有"，这是接口的特性。
//要实现一个接口，使用 implements 操作符。类中必须实现接口中定义的所有方法，否则会报一个致命错误。类可以实现多个接口，用逗号来分隔多个接口的名称
//接口类似oc中的协议
//接口只能定义方法，不能定义属性
interface TrainInterface{
  public function speed($distance,$time);
}
/**
* 
*/
class Train extends Car implements TrainInterface
{
	
	function __construct()
	{
		
	}
	public function speed($distance,$time)
	{
		$speedValue=$distance/$time;
		echo "速度:".$speedValue."<br>";
	}
}
$train1=new Train();
$train1->describeCar();
$train1->speed(11123,4);



//抽象类:任何一个类，如果它里面至少有一个方法是被声明为抽象的，那么这个类就必须被声明为抽象的
//定义为抽象的类不能被实例化
//被定义为抽象的方法只是声明了其调用方式（参数），不能定义其具体的功能实现
//继承一个抽象类的时候，子类必须定义父类中的所有抽象方法
//这些方法的访问控制必须和父类中一样（或者更为宽松）。例如某个抽象方法被声明为受保护的，那么子类中实现的方法就应该声明为受保护的或者公有的
 /**
* 
*/
abstract class AbstractClass
{
  abstract public function abstractFun();
   public function normalFun()
   {
     echo "我是normalFun"."<br>";
   }


 }

/**
* 
*/
//PHP 5 新增了一个 final 关键字。如果父类中的方法被声明为 final，则子类无法覆盖该方法。如果一个类被声明为 final，则不能被继承。

//PHP 不会在子类的构造方法中自动的调用父类的构造方法。要执行父类的构造方法，需要在子类的构造方法中调用 parent::__construct() 。

//除了$this调用属性可以不带$符号，其他情况都会带
class SubClass extends AbstractClass
{
  //static用来修饰类中的变量或方法时，都是用类调用的(static方法也可以用对象调用)，不能用$this调用，用::衔接，相当于是类方法和类变量
static private $num=10;
static public function staticFun()
{
  echo "我是staticFun"."<br>";
}
 public function abstractFun(){
self::$num=11;
echo self::$num;
 echo "我是abstract方法实现"."<br>";

} 
}

$sub=new SubClass;
SubClass::staticFun();
$sub->abstractFun();
$sub->normalFun();
?>